home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / (A)Z / (A)Z7.ADF / C / beep / beep.c next >
C/C++ Source or Header  |  1986-10-31  |  6KB  |  245 lines

  1. /*****************************************************************************
  2.  *
  3.  * VT100-like Beep Sound Example        22 February 1986
  4.  *
  5.  * Copyright (c) 1986 Sam Dicker, Commodore/Amiga Inc.
  6.  * This is public domain software.  Permission is granted to copy and use
  7.  * this software as long as this notice is included.
  8.  *
  9.  * This module makes a beep sound like the CTRL-G on a VT100 terminal.
  10.  *
  11.  * Calling VTBeep() starts the sound which stops when it times out.
  12.  * Calling it again, while it is playing, only restarts the timer.
  13.  * Call KillVTBeep() to kill any beeps in progress before exiting your
  14.  * main program.
  15.  *
  16.  * VTBeep() and KillVTBeep() are re-entrant but cannot be used in interrupt
  17.  * code.
  18.  *
  19.  * The audio in this example is very crude.  It is more of an example of
  20.  * using the timer device and multi-tasking.  I sincerely hope, if it appears
  21.  * in any products, that it is only used as an authentic 'cheap terminal'
  22.  * sound.  A little more code can produce much better (less obnoxious) sound.
  23.  *
  24.  * VT100 is a trademark of Digital Equipment Corporation.
  25.  *
  26.  *****************************************************************************/
  27.  
  28. #include "exec/types.h"
  29. #include "exec/errors.h"
  30. #include "exec/memory.h"
  31. #include "devices/timer.h"
  32. #include "devices/audio.h"
  33. #include "libraries/dos.h"
  34.  
  35. #define BEEPNAME    "VTBeep"
  36. #define BEEPSIZE    10
  37. #define BEEPFREQ    1000
  38. #define COLORCLOCK    3579545
  39. #define SIGB_BEEP    31
  40. #define SIGF_BEEP    (1 << 31)
  41. #define SIGF_PORT    (1 << replyPort->mp_SigBit)
  42.  
  43. /* channel allocation map (try left channel; if unavailable try right) */
  44. UBYTE allocationMap[] = { 1, 8, 2, 4 };
  45.  
  46.  
  47. /* make beep sound */
  48.  
  49. VTBeep()
  50. {
  51.     struct Task *beepTCB;
  52.     VOID beepTask();
  53.  
  54.     /* prevent beep child task, if it already exists, from going away before
  55.      * it is signaled */
  56.     Forbid();
  57.  
  58.     /* find the task by name */
  59.     beepTCB = (struct Task *)FindTask(BEEPNAME);
  60.  
  61.     /* check if the task exists */
  62.     if (beepTCB == NULL)
  63.  
  64.     /* it doesn't exist, so create it */
  65.     beepTCB = (struct Task *)CreateTask(BEEPNAME, 25, beepTask, 500);
  66.  
  67.     else
  68.  
  69.     /* it already exist so signal it so restart it's timer */
  70.     Signal(beepTCB, SIGF_BEEP);
  71.  
  72.     Permit();
  73.  
  74.     /* return success */
  75.     return(beepTCB != NULL);
  76. }
  77.  
  78.  
  79. /* kill any beep sounds in progress.  This is necessary before exiting the
  80.  * main program; otherwise, if a beep is playing, when the beep times out
  81.  * and the child task wakes up its code segment may be gone */
  82.  
  83. KillVTBeep()
  84. {
  85.     struct Task *beepTCB;
  86.  
  87.     do {
  88.  
  89.     /* prevent beep child task, if it already exists, from going away
  90.      * before it is signaled */
  91.     Forbid();
  92.  
  93.     /* find the task by name */
  94.     beepTCB = (struct Task *)FindTask(BEEPNAME);
  95.  
  96.     /* check if the task exists */
  97.     if (beepTCB != NULL) {
  98.  
  99.         /* it already exist so signal it so go away */
  100.         Signal(beepTCB, SIGBREAKF_CTRL_C);
  101.  
  102.         /* give it a chance to wake up, if it is lower priority */
  103.         Delay(10);
  104.  
  105.     }
  106.     Permit();
  107.  
  108.     /* if it existed, kill it again */
  109.     } while (beepTCB != NULL);
  110. }
  111.  
  112.  
  113. /* beep sound child task */
  114.  
  115. VOID beepTask()
  116. {
  117.     struct MsgPort *replyPort;
  118.     struct timerequest *timerIOB;
  119.     struct IOAudio *audioIOB;
  120.     UBYTE *beepWave;
  121.     ULONG signals;
  122.  
  123.     /* allocate signal used to re-start beep */
  124.     if (AllocSignal(SIGB_BEEP) == SIGB_BEEP) {
  125.  
  126.     /* create reply port for timer and sound I/O block */
  127.     replyPort = (struct MsgPort *)CreatePort(NULL);
  128.  
  129.     if (replyPort != NULL) {
  130.  
  131.         /* create timer I/O block */
  132.         timerIOB = (struct timerequest *)
  133.             CreateExtIO(replyPort, sizeof(struct timerequest));
  134.  
  135.         if (timerIOB != NULL) {
  136.  
  137.         /* open timer device */
  138.         if (OpenDevice(TIMERNAME, UNIT_VBLANK, timerIOB, 0) == 0) {
  139.  
  140.             timerIOB->tr_node.io_Command = TR_ADDREQUEST;
  141.  
  142.             /* create beep waveform */
  143.  
  144.             beepWave = (UBYTE *)AllocMem(BEEPSIZE,
  145.                 MEMF_CHIP | MEMF_CLEAR);
  146.             if (beepWave != 0) {
  147.             beepWave[0] = 100;
  148.  
  149.  
  150.             /* create audio I/O block */
  151.             audioIOB = (struct IOAudio *)
  152.                 CreateExtIO(replyPort, sizeof(struct IOAudio));
  153.             if (audioIOB != NULL) {
  154.  
  155.                 /* setup audio I/O block to allocate a channel
  156.                  * when the audio device is opened (see Volume 1 of
  157.                  * the Amiga ROM Kernel Manual - Audio Device
  158.                  * chapter and Volume 2 of the Amiga ROM Kernel
  159.                  * Manual - Device Summaries appendix for details)
  160.                  */
  161.  
  162.                 audioIOB->ioa_Request.io_Message.mn_Node.ln_Pri =
  163.                     85;
  164.                 audioIOB->ioa_Data = allocationMap;
  165.                 audioIOB->ioa_Length = sizeof(allocationMap);
  166.  
  167.  
  168.                 /* open the audio device */
  169.                 if (OpenDevice(AUDIONAME, 0, audioIOB, 0) == 0) {
  170.  
  171.                 /* setup the audio I/O block to play sound */
  172.  
  173.                 audioIOB->ioa_Request.io_Command = CMD_WRITE;
  174.                 audioIOB->ioa_Request.io_Flags = ADIOF_PERVOL;
  175.                 audioIOB->ioa_Data = beepWave;
  176.                 audioIOB->ioa_Length = BEEPSIZE;
  177.                 audioIOB->ioa_Period =
  178.                     COLORCLOCK / (BEEPSIZE * BEEPFREQ);
  179.                 audioIOB->ioa_Volume = 64;
  180.  
  181.  
  182.                 /* start the sound */
  183.                 BeginIO(audioIOB);
  184.  
  185.                 /* from this point on the task in cannot
  186.                    be pre-empted.  This prevents the
  187.                    parent task from signaling it to
  188.                    restart the timer while it is cleaning
  189.                    up */
  190.                 
  191.                 Forbid();
  192.                 do {
  193.  
  194.                     /* start the timer */
  195.  
  196.                     timerIOB->tr_time.tv_secs = 0;
  197.                     timerIOB->tr_time.tv_micro = 250000;
  198.                     SendIO(timerIOB);
  199.  
  200.                     
  201.                     /* wait for:
  202.                     . the timer to time out,
  203.                     . the audio I/O block to return
  204.                       (indicating an error had occurred),
  205.                     . a signal to restart to timer, or
  206.                     . a signal to quit */
  207.  
  208.                     do
  209.                     signals = Wait(SIGBREAKF_CTRL_C |
  210.                         SIGF_BEEP | SIGF_PORT);
  211.                     while ((signals & SIGF_PORT) != 0 &&
  212.                         CheckIO(timerIOB) == 0 &&
  213.                         CheckIO(audioIOB) == 0);
  214.  
  215.  
  216.                     /* if the timer is still going, kill it */
  217.  
  218.                     if (CheckIO(timerIOB) == 0) {
  219.                     AbortIO(timerIOB);
  220.                     WaitIO(timerIOB);
  221.                     }
  222.  
  223.  
  224.                 /* restart the timer if signaled */
  225.                 } while ((signals & SIGF_BEEP) != 0);
  226.  
  227.                 /* clean up */
  228.  
  229.                 /* closing the audio device kills the sound
  230.                  * and frees the channels */
  231.                 CloseDevice(audioIOB);
  232.                 }
  233.                 DeleteExtIO(audioIOB);
  234.             }
  235.             FreeMem(beepWave, BEEPSIZE);
  236.             }
  237.             CloseDevice(timerIOB);
  238.         }
  239.         DeleteExtIO(timerIOB);
  240.         }
  241.         DeletePort(replyPort);
  242.     }
  243.     }
  244. }
  245.